﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.Web.Http;
using Newtonsoft.Json.Linq;
using WebServiceTMS.Helpers;
using Newtonsoft.Json;
using System.Data.Entity.SqlServer;
namespace WebServiceTMS.Controllers
{
    public class TMSBugs
    {
        public string Name { get; set; }
        public string Task { get; set; }
        public int Number { get; set; }
        public string Id { get; set; }
        public string Type { get; set; }
        public string Description { get; set; }
        public string Category { get; set; }
        public string ReportedOn { get; set; }
        public string ReportedBy { get; set; }
        public string Status { get; set; }
        public string UpdatedOn { get; set; }
        public string LastUpdateBy { get; set; }
        public string Version { get; set; }
    }
    public class BugController : ApiController
    {
        //POST api/Bug/AddNewBug
        [HttpPost]
        [ActionName("AddNewBug")]
        public HttpResponseMessage AddNewBug(HttpRequestMessage request)
        {
            try
            {
                var content = request.Content;
                var jsonContent = content.ReadAsStringAsync().Result;
                var userObject = JObject.Parse(jsonContent);
                var tmp = new Dictionary<string, string>();
                foreach (KeyValuePair<String, JToken> resp in userObject)
                {
                    tmp.Add(resp.Key, resp.Value.ToString());
                }

                if (tmp.Count > 0)
                {
                    string userId = null;
                    bool isSuccessUserId = tmp.TryGetValue("UserId", out userId);
                    string taskId = null;
                    bool isSuccessTaskId = tmp.TryGetValue("TaskId", out taskId);
                    string name = null;
                    bool isSuccessName = tmp.TryGetValue("Name", out name);
                    string bugDescription = null;
                    bool isSuccessBugDescription = tmp.TryGetValue("Description", out bugDescription);
                    string number = null;
                    bool isSuccessNumber = tmp.TryGetValue("Number", out number);
                    string type = null;
                    bool isSuccessType = tmp.TryGetValue("Type", out type);
                    string category = null;
                    bool isSuccessCategory = tmp.TryGetValue("Category", out category);
                    string version = null;
                    bool isSuccessVersion = tmp.TryGetValue("Version", out version);
                    userId = TMSCryptography.Decrypt(userId);
                    if (isSuccessUserId && isSuccessTaskId && isSuccessName && isSuccessBugDescription &&
                        isSuccessNumber && isSuccessType && isSuccessCategory && isSuccessVersion)
                    {
                        int userIdNumeric;
                        bool isUserIdANumber = int.TryParse(userId, out userIdNumeric);
                        int taskIdNumeric;
                        bool isTaskIdANumber = int.TryParse(taskId, out taskIdNumeric);
                        int numberNumeric;
                        bool isNumberANumber = int.TryParse(number, out numberNumeric);
                        if (isUserIdANumber && isTaskIdANumber && isNumberANumber)
                        {
                            return AddNewBugHelper(userIdNumeric, taskIdNumeric, name, numberNumeric,
                                type, bugDescription, category, version);
                        }
                        return HttpResponseHelper.CreateHttpResponse("error", "Parameter error");
                    }
                    return HttpResponseHelper.CreateHttpResponse("error", "Some parameters have wrong format or empty!");
                }
                return HttpResponseHelper.CreateHttpResponse("error", "Parameters list is empty");
            }
            catch (Exception ex)
            {
                return HttpResponseHelper.CreateHttpResponse("server_error", ex.Message);
            }
        }
 
        //POST api/Bug/RemoveBug
        [HttpPost]
        [ActionName("RemoveBug")]
        public HttpResponseMessage RemoveBug(HttpRequestMessage request)
        {
            try
            {
                var content = request.Content;
                var jsonContent = content.ReadAsStringAsync().Result;
                var userObject = JObject.Parse(jsonContent);
                var tmp = new Dictionary<string, string>();
                foreach (KeyValuePair<String, JToken> resp in userObject)
                {
                    tmp.Add(resp.Key, resp.Value.ToString());
                }

                if (tmp.Count > 0)
                {
                    string userId = null;
                    bool isSuccessUserId = tmp.TryGetValue("UserId", out userId);
                    string bugId = null;
                    bool isSuccessBugId = tmp.TryGetValue("BugId", out bugId);
                    userId = TMSCryptography.Decrypt(userId);
                    bugId = TMSCryptography.Decrypt(bugId);
                    if (isSuccessUserId && isSuccessBugId)
                    {
                        int userIdNumeric;
                        bool isUserIdANumber = int.TryParse(userId, out userIdNumeric);
                        int bugIdNumeric;
                        bool isBugIdNumber = int.TryParse(bugId, out bugIdNumeric);
                        if (isUserIdANumber && isBugIdNumber)
                        {
                            return RemoveBugHelper(userIdNumeric, bugIdNumeric);
                        }
                        return HttpResponseHelper.CreateHttpResponse("error", "Parameter error");
                    }
                    return HttpResponseHelper.CreateHttpResponse("error", "Some parameters have wrong format or empty!");
                }
                return HttpResponseHelper.CreateHttpResponse("error", "Parameters list is empty");
            }
            catch (Exception ex)
            {
                return HttpResponseHelper.CreateHttpResponse("server_error", ex.Message);
            }
        }

        //POST api/Bug/EditBug
        [HttpPost]
        [ActionName("EditBug")]
        public HttpResponseMessage EditBug(HttpRequestMessage request)
        {
            try
            {
                var content = request.Content;
                var jsonContent = content.ReadAsStringAsync().Result;
                var userObject = JObject.Parse(jsonContent);
                var tmp = new Dictionary<string, string>();
                foreach (KeyValuePair<String, JToken> resp in userObject)
                {
                    tmp.Add(resp.Key, resp.Value.ToString());
                }

                if (tmp.Count > 0)
                {
                    string userId = null;
                    bool isSuccessUserId = tmp.TryGetValue("UserId", out userId);
                    string bugId = null;
                    bool isSuccessBugId = tmp.TryGetValue("BugId", out bugId);
                    string name = null;
                    bool isSuccessName = tmp.TryGetValue("Name", out name);
                    string bugDescription = null;
                    bool isSuccessBugDescription = tmp.TryGetValue("Description", out bugDescription);
                    string type = null;
                    bool isSuccessType = tmp.TryGetValue("Type", out type);
                    string category = null;
                    bool isSuccessCategory = tmp.TryGetValue("Category", out category);
                    string version = null;
                    bool isSuccessVersion = tmp.TryGetValue("Version", out version);
                    userId = TMSCryptography.Decrypt(userId);
                    bugId = TMSCryptography.Decrypt(bugId);
                    if (isSuccessUserId && isSuccessBugId && isSuccessName && isSuccessBugDescription &&
                        isSuccessType && isSuccessCategory && isSuccessVersion)
                    {
                        int userIdNumeric;
                        bool isUserIdANumber = int.TryParse(userId, out userIdNumeric);
                        int bugIdNumeric;
                        bool isBugIdANumber = int.TryParse(bugId, out bugIdNumeric);
                        if (isUserIdANumber && isBugIdANumber)
                        {
                            return EditBugHelper(userIdNumeric, bugIdNumeric, name,
                                type, category, bugDescription, version);
                        }
                        return HttpResponseHelper.CreateHttpResponse("error", "Parameter error");
                    }
                    return HttpResponseHelper.CreateHttpResponse("error", "Some parameters are empty!");
                }
                return HttpResponseHelper.CreateHttpResponse("error", "Parameters list is empty");
            }
            catch (Exception ex)
            {
                return HttpResponseHelper.CreateHttpResponse("server_error", ex.Message);
            }
        }
     
        //POST api/Bug/ChangeBugStatus
        [HttpPost]
        [ActionName("ChangeBugStatus")]
        public HttpResponseMessage ChangeBugStatus(HttpRequestMessage request)
        {
            try
            {
                var content = request.Content;
                var jsonContent = content.ReadAsStringAsync().Result;
                var userObject = JObject.Parse(jsonContent);
                var tmp = new Dictionary<string, string>();
                foreach (KeyValuePair<String, JToken> resp in userObject)
                {
                    tmp.Add(resp.Key, resp.Value.ToString());
                }

                if (tmp.Count > 0)
                {
                    string userId = null;
                    bool isSuccessUserId = tmp.TryGetValue("UserId", out userId);
                    string bugId = null;
                    bool isSuccessBugId = tmp.TryGetValue("BugId", out bugId);
                    string status = null;
                    bool isSuccessStatus = tmp.TryGetValue("Status", out status);
                    userId = TMSCryptography.Decrypt(userId);
                    bugId = TMSCryptography.Decrypt(bugId);
                    if (isSuccessUserId && isSuccessBugId && isSuccessStatus)
                    {
                        int userIdNumeric;
                        bool isUserIdANumber = int.TryParse(userId, out userIdNumeric);
                        int bugIdNumeric;
                        bool isBugIdANumber = int.TryParse(bugId, out bugIdNumeric);
                        if (isUserIdANumber && isBugIdANumber)
                        {
                            return ChangeBugStatusHelper(userIdNumeric, bugIdNumeric, status);
                        }
                        return HttpResponseHelper.CreateHttpResponse("error", "Parameter error");
                    }
                    return HttpResponseHelper.CreateHttpResponse("error", "Some parameters are empty!");
                }
                return HttpResponseHelper.CreateHttpResponse("error", "Parameters list is empty");
            }
            catch (Exception ex)
            {
                return HttpResponseHelper.CreateHttpResponse("server_error", ex.Message);
            }
        }

        //GET api/Bug/GetAllBugsInTask
        [HttpGet]
        [ActionName("GetAllBugsInTask")]
        public HttpResponseMessage GetAllBugsInTask(HttpRequestMessage request)
        {
            try
            {
                var content = request.Content;
                var jsonContent = content.ReadAsStringAsync().Result;
                var userObject = JObject.Parse(jsonContent);
                var tmp = new Dictionary<string, string>();
                foreach (KeyValuePair<String, JToken> resp in userObject)
                {
                    tmp.Add(resp.Key, resp.Value.ToString());
                }

                if (tmp.Count > 0)
                {
                    string taskId = null;
                    bool isSuccessTaskId = tmp.TryGetValue("TaskId", out taskId);
                    taskId = TMSCryptography.Decrypt(taskId);
                    if (isSuccessTaskId)
                    {
                        int taskIdNumeric;
                        bool isTaskIdANumber = int.TryParse(taskId, out taskIdNumeric);
                        if (isTaskIdANumber)
                        {
                            return GetAllBugsInTaskHelper(taskIdNumeric);
                        }
                        return HttpResponseHelper.CreateHttpResponse("error", "Parameter error");
                    }
                    return HttpResponseHelper.CreateHttpResponse("error", "Some parameters have wrong format or empty!");
                }
                return HttpResponseHelper.CreateHttpResponse("error", "Parameters list is empty");
            }
            catch (Exception ex)
            {
                return HttpResponseHelper.CreateHttpResponse("server_error", ex.Message);
            }
        }

        //GET api/Bug/GetAllBugsByUser
        [HttpGet]
        [ActionName("GetAllBugsByUser")]
        public HttpResponseMessage GetAllBugsByUser(HttpRequestMessage request)
        {
            try
            {
                var content = request.Content;
                var jsonContent = content.ReadAsStringAsync().Result;
                var userObject = JObject.Parse(jsonContent);
                var tmp = new Dictionary<string, string>();
                foreach (KeyValuePair<String, JToken> resp in userObject)
                {
                    tmp.Add(resp.Key, resp.Value.ToString());
                }

                if (tmp.Count > 0)
                {
                    string userId = null;
                    bool isSuccessUserId = tmp.TryGetValue("UserId", out userId);
                    string taskId = null;
                    bool isSuccessTaskId = tmp.TryGetValue("TaskId", out taskId);
                    userId = TMSCryptography.Decrypt(userId);
                    taskId = TMSCryptography.Decrypt(taskId);
                    if (isSuccessTaskId && isSuccessTaskId)
                    {
                        int userIdNumeric;
                        bool isUserIdANumber = int.TryParse(userId, out userIdNumeric);
                        int taskIdNumeric;
                        bool isTaskIdANumber = int.TryParse(taskId, out taskIdNumeric);
                        if (isUserIdANumber && isTaskIdANumber)
                        {
                            return GetAllBugsByUserHelper(userIdNumeric, taskIdNumeric);
                        }
                        return HttpResponseHelper.CreateHttpResponse("error", "Parameter error");
                    }
                    return HttpResponseHelper.CreateHttpResponse("error", "Some parameters have wrong format or empty!");
                }
                return HttpResponseHelper.CreateHttpResponse("error", "Parameters list is empty");
            }
            catch (Exception ex)
            {
                return HttpResponseHelper.CreateHttpResponse("server_error", ex.Message);
            }
        }

        //GET api/Bug/GetBug
        [HttpGet]
        [ActionName("GetBug")]
        public HttpResponseMessage GetBug(HttpRequestMessage request)
        {
            try
            {
                var content = request.Content;
                var jsonContent = content.ReadAsStringAsync().Result;
                var userObject = JObject.Parse(jsonContent);
                var tmp = new Dictionary<string, string>();
                foreach (KeyValuePair<String, JToken> resp in userObject)
                {
                    tmp.Add(resp.Key, resp.Value.ToString());
                }

                if (tmp.Count > 0)
                {
                    string bugId = null;
                    bool isSuccessBugId = tmp.TryGetValue("BugId", out bugId);
                    bugId = TMSCryptography.Decrypt(bugId);
                    if (isSuccessBugId)
                    {
                        int bugIdNumeric;
                        bool isBugIdANumber = int.TryParse(bugId, out bugIdNumeric);
                        if (isBugIdANumber)
                        {
                            return GetBugHelper(bugIdNumeric);
                        }
                        return HttpResponseHelper.CreateHttpResponse("error", "Parameter error");
                    }
                    return HttpResponseHelper.CreateHttpResponse("error", "Some parameters have wrong format or empty!");
                }
                return HttpResponseHelper.CreateHttpResponse("error", "Parameters list is empty");
            }
            catch (Exception ex)
            {
                return HttpResponseHelper.CreateHttpResponse("server_error", ex.Message);
            }
        }

        private HttpResponseMessage AddNewBugHelper(int userId, int taskId, string name, int number,
             string type, string description,  string category, string version)
        {
            try
            {
                using (var context = new TMSEntities())
                {
                    var user = context.Users.FirstOrDefault(u => u.Id == userId);
                    if (user != null)
                    {
                        var newBug = new Bugs
                        {
                            Task = taskId,
                            Name = name,
                            Number = number,
                            Type = type,
                            Description = description,
                            Category = category,
                            ReportedOn = DateTime.Now,
                            Version = version,
                            ReportedBy = userId,
                            LastUpdateBy = userId,
                            UpdatedOn = DateTime.Now,
                            Status = "New"
                        };
                        context.Bugs.Add(newBug);
                        context.SaveChanges();
                        return HttpResponseHelper.CreateHttpResponse("success", "");
                    }
                    return HttpResponseHelper.CreateHttpResponse("error", "There is no such user");
                }
                    
            }
            catch (Exception ex)
            {
                return HttpResponseHelper.CreateHttpResponse("server_error", ex.Message);
            }
        }

         private HttpResponseMessage RemoveBugHelper(int userId, int bugId)
         {
             try
             {
                 using (var context = new TMSEntities())
                 {
                     var user = context.Users.FirstOrDefault(u => u.Id == userId);
                     if (user != null)
                     {
                         var bug = context.Bugs.FirstOrDefault(b => b.Id == bugId);
                         if (bug != null)
                         {
                             if (user.Status == "Admin" || user.Status == "Manager" || bug.ReportedBy == user.Id)
                             {
                                 context.Bugs.Remove(bug);
                                 context.SaveChanges();
                                 return HttpResponseHelper.CreateHttpResponse("success", "");
                             }
                             return HttpResponseHelper.CreateHttpResponse("error", "You have no permissions to remove this bug");
                         }
                         return HttpResponseHelper.CreateHttpResponse("error", "There is no such bug in the system");
                     }
                     return HttpResponseHelper.CreateHttpResponse("error", "Invalid user");
                 }
             }
             catch (Exception ex)
             {
                 return HttpResponseHelper.CreateHttpResponse("server_error", ex.Message);
             }
         }

         private HttpResponseMessage EditBugHelper(int userId, int bugId, string name, string type, 
             string category,string bugDescription, string version)
         {
             try
             {
                 using (var context = new TMSEntities())
                 {
                     var user = context.Users.FirstOrDefault(us => us.Id == userId);
                     if (user != null)
                     {
                         var bug = context.Bugs.FirstOrDefault(b => b.Id == bugId);
                         if (bug != null)
                         {
                             bug.Name = name;
                             bug.Type = type;
                             bug.Category = category;
                             bug.Description = bugDescription;
                             bug.Version = version;
                             context.SaveChanges();
                             return HttpResponseHelper.CreateHttpResponse("success", "");
                         }
                         return HttpResponseHelper.CreateHttpResponse("error", "There is no such bug!");
                     }
                     return HttpResponseHelper.CreateHttpResponse("error", "There is no such user!");
                 }
             }
             catch (Exception ex)
             {
                 return HttpResponseHelper.CreateHttpResponse("server_error", ex.Message);
             }
         }

         private HttpResponseMessage ChangeBugStatusHelper(int userId, int bugId, string status)
         {
             try
             {
                 using (var context = new TMSEntities())
                 {
                     var user = context.Users.FirstOrDefault(us => us.Id == userId);
                     if (user != null)
                     {
                         var bug = context.Bugs.FirstOrDefault(b => b.Id == bugId);
                         if (bug != null)
                         {
                             if (status == "Closed" || status == "Reopened" && bug.ReportedBy != userId)
                             {
                                 return HttpResponseHelper.CreateHttpResponse
                                     ("error", "You have no rights to close or reopen not your bug!");
                             }
                             else
                             {
                                 bug.Status = status;
                                 context.SaveChanges();
                                 return HttpResponseHelper.CreateHttpResponse("success", "");
                             }
                         }
                         return HttpResponseHelper.CreateHttpResponse("error", "There is no such bug!");
                     }
                     return HttpResponseHelper.CreateHttpResponse("error", "There is no such user!");
                 }
             }
             catch (Exception ex)
             {
                 return HttpResponseHelper.CreateHttpResponse("server_error", ex.Message);
             }
         }

        private HttpResponseMessage GetAllBugsInTaskHelper(int taskId)
        {
            try
            {
                using (var context = new TMSEntities())
                {
                    var allTasks = context.Tasks.ToList();
                    var query = from b in context.Bugs
                                where b.Task == taskId
                                select new TMSBugs
                                {
                                    Id = SqlFunctions.StringConvert((double)b.Id).Trim(),
                                    Name = b.Name,
                                    Description = b.Description,
                                    Task = SqlFunctions.StringConvert((double)allTasks.First(t => t.Id == taskId).Id).Trim(),
                                    Number = b.Number,
                                    Status = b.Status,
                                    Type = b.Type,
                                    Version = b.Version,
                                    ReportedBy = SqlFunctions.StringConvert((double)b.ReportedBy).Trim(),
                                    ReportedOn = b.ReportedOn.ToShortDateString(),
                                    UpdatedOn = b.UpdatedOn.ToShortDateString()
                                };
                    return GetJsonBugs(query.ToArray());
                }
            }
            catch (Exception ex)
            {
                return HttpResponseHelper.CreateHttpResponse("server_error", ex.Message);
            }
        }

        private HttpResponseMessage GetAllBugsByUserHelper(int userId, int taskId)
        {
            try
            {
                using (var context = new TMSEntities())
                {
                    var users = context.Users.ToList();
                    var allTasks = context.Goals.ToList();
                    var query = from b in context.Bugs
                                where b.ReportedBy == userId ||
                                b.LastUpdateBy == userId
                                select new TMSBugs
                                {
                                    Id = SqlFunctions.StringConvert((double)b.Id).Trim(),
                                    Name = b.Name,
                                    Description = b.Description,
                                    Task = SqlFunctions.StringConvert((double)allTasks.First(t => t.Id == taskId).Id).Trim(),
                                    Number = b.Number,
                                    Status = b.Status,
                                    Type = b.Type,
                                    Version = b.Version,
                                    ReportedBy = SqlFunctions.StringConvert((double)b.ReportedBy).Trim(),
                                    ReportedOn = b.ReportedOn.ToShortDateString(),
                                    UpdatedOn = b.UpdatedOn.ToShortDateString()
                                };
                    return GetJsonBugs(query.ToArray());
                }
            }
            catch (Exception ex)
            {
                return HttpResponseHelper.CreateHttpResponse("server_error", ex.Message);
            }
        }

        private HttpResponseMessage GetBugHelper(int bugId)
        {
            try
            {
                using (var context = new TMSEntities())
                {
                    var bug = from b in context.Bugs
                              where b.Id == bugId
                              select new TMSBugs
                              {
                                  Id = SqlFunctions.StringConvert((double)b.Id).Trim(),
                                  Name = b.Name,
                                  Description = b.Description,
                                  Task = SqlFunctions.StringConvert((double)b.Task).Trim(),
                                  Number = b.Number,
                                  Status = b.Status,
                                  Type = b.Type,
                                  Version = b.Version,
                                  ReportedBy = SqlFunctions.StringConvert((double)b.ReportedBy).Trim(),
                                  ReportedOn = b.ReportedOn.ToShortDateString(),
                                  UpdatedOn = b.UpdatedOn.ToShortDateString()
                              };
                    return HttpResponseHelper.CreateHttpResponse("success", "Bug");
                }
            }
            catch (Exception ex)
            {
                return HttpResponseHelper.CreateHttpResponse("server_error", ex.Message);
            }
        }


        private HttpResponseMessage GetJsonBugs(TMSBugs[] bugListInTask)
        {
            if (bugListInTask.Any())
            {
                for (var i = 0; i < bugListInTask.Count(); i++)
                {
                    bugListInTask[i].Id = TMSCryptography.Encrypt(bugListInTask[i].Id);
                    bugListInTask[i].ReportedBy = TMSCryptography.Encrypt(bugListInTask[i].ReportedBy);
                    bugListInTask[i].Task = TMSCryptography.Encrypt(bugListInTask[i].Task);
                }
                var jsonResponse = JsonConvert.SerializeObject(bugListInTask);
                return HttpResponseHelper.CreateHttpResponse("success", jsonResponse);
            }
            return HttpResponseHelper.CreateHttpResponse("success", "[]");
        }

        private int GetLastPosition(int bugId, int taskId)
        {
            using (var context = new TMSEntities())
            {
                var bugs = from bug in context.Bugs
                           where bug.Task == taskId
                           select bug;
                var bugList = bugs.ToList();
                if (bugs.Count() != 0) return bugList.Max(b => b.Number);    
                return 0;
            }
        }
    }
}
